#pragma once
#include <conio.h>
#include <iostream>
#include "Console.h"
#include <mutex>
#include <deque>
#include <thread>
#include <string>
using namespace std;


mutex mutex_cout;
deque<char> p1Keys;
deque<char> p2Keys;

class Position
{
public:
	int xPos, yPos;
	int previousX, previousY;
	string name;

	Position()
	{

	}

	Position(int xPos, int yPos, int previousX, int previousY, string name)
	{
		this->xPos = xPos;
		this->yPos = yPos;
		this->previousX = previousX;
		this->previousY = previousY;
		this->name = name;
	}

	friend bool operator==(const Position& lop, const Position& rop)
	{
		return ((lop.xPos == rop.xPos) && (lop.yPos == rop.yPos));
	}
	
};
deque<Position> positioner;


class Game
{
private:
	char move;
public:
	bool Caught = false;
	Game()
	{
	}

	void printBoard()
	{
		if (positioner.empty())
		{	
			Course::Console::gotoxy(20, 0);
			for (int i = 0; i < 20; i++)
			{
				cout << "|" << endl;
				Course::Console::gotoxy(20, i+1);
			}
			Course::Console::gotoxy(0, 20);
			for (int i = 0; i < 20; i++)
			{
				cout << "-";
			}
			Course::Console::gotoxy(25, 10);
			cout << "Player 1 is the chaser (W,A,S,D)";
			Course::Console::gotoxy(25, 11);
			cout << "Player 2 is the runner (8,4,5,6)";
		}

		else
		{
			CheckIfCaught();
			Position temp = positioner.front();
			Course::Console::gotoxy(temp.previousX, temp.previousY);
			cout << " ";
			Course::Console::gotoxy(temp.xPos, temp.yPos);
			cout << temp.name;
			positioner.pop_front();

			Course::Console::gotoxy(20, 0);
			for (int i = 0; i < 20; i++)
			{
				cout << "|" << endl;
				Course::Console::gotoxy(20, i + 1);
			}
			Course::Console::gotoxy(0, 20);
			for (int i = 0; i < 20; i++)
			{
				cout << "-";
			}
			Course::Console::gotoxy(25, 10);
			cout << "Player 1 is the chaser (W,A,S,D)";
			Course::Console::gotoxy(25, 11);
			cout << "Player 2 is the runner (8,4,5,6)";
		}
	}

	void CheckIfCaught()
	{
		for (auto it = positioner.begin(); it != positioner.end() - 1; it++)
		{
			Position temp1(it->xPos, it->yPos, it->previousX, it->previousY, it->name);
			auto it2 = it + 1;
			Position temp2(it2->xPos, it2->yPos, it2->previousX, it2->previousY, it2->name);
			if (temp1 == temp2)
			{
				Caught = true;
				GameFinished();
			}
		}
	}
	void operator()()
	{
		while (1)
		{
			if (_kbhit())
			{
				move = _getch();
				
				if (move == 'm')
				{
					break;
				}

				else
				{
					mutex_cout.lock();

					if (move == 'w' || move == 'a' || move == 's' || move == 'd')
					{
						p1Keys.push_front(move);
					}

					else if (move == '8' || move == '4' || move == '5' || move == '6')
					{
						p2Keys.push_front(move);					
					}

					mutex_cout.unlock();
				}
				
			}
			mutex_cout.lock();
			printBoard();
			mutex_cout.unlock();
			this_thread::sleep_for(chrono::milliseconds(10));
		}

	}

	void GameFinished()
	{
		mutex_cout.unlock();
		exit(EXIT_SUCCESS);
	}

	~Game()
	{
	}
};

